package cn.zwk.drawing.application.controller;

import cn.zwk.drawing.domain.execution.model.ExecutionRequest;
import cn.zwk.drawing.domain.execution.model.ExecutionResult;
import cn.zwk.drawing.domain.execution.service.ExecutionDomainService;
import cn.zwk.drawing.application.dto.ExecutionRequestDto;
import cn.zwk.drawing.application.dto.ExecutionResponseDto;
import cn.zwk.drawing.application.dto.ApiResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

/**
 * 脚本执行API控制器
 */
@Slf4j
@RestController
@RequestMapping("/api/v1/scripts")
@RequiredArgsConstructor
@CrossOrigin(origins = "*")
public class ScriptExecutionController {

    private final ExecutionDomainService executionService;

    /**
     * 执行脚本
     */
    @PostMapping("/execute")
    public ResponseEntity<ApiResponse<ExecutionResponseDto>> executeScript(
            @Valid @RequestBody ExecutionRequestDto requestDto) {

        log.info("执行脚本: {} -> {}", requestDto.getNodeId(), requestDto.getCapabilityId());

        try {
            // 构建执行请求
            ExecutionRequest request = ExecutionRequest.builder()
                    .executionId(UUID.randomUUID().toString())
                    .nodeId(requestDto.getNodeId())
                    .capabilityId(requestDto.getCapabilityId())
                    .parameters(requestDto.getParameters())
                    .timeout(requestDto.getTimeout() != null ? requestDto.getTimeout() : 60)
                    .async(false)
                    .requestedAt(LocalDateTime.now())
                    .source("web")
                    .userId("system") // 实际应从认证信息获取
                    .build();

            // 验证请求
            if (!request.isValid()) {
                return ResponseEntity.badRequest()
                        .body(ApiResponse.error("无效的执行请求"));
            }

            // 执行脚本
            ExecutionResult result = executionService.executeScript(request);

            // 构建响应
            ExecutionResponseDto response = ExecutionResponseDto.builder()
                    .executionId(result.getExecutionId())
                    .nodeId(result.getNodeId())
                    .capabilityId(result.getCapabilityId())
                    .status(result.getStatus().getCode())
                    .output(result.getOutput())
                    .errorMessage(result.getErrorMessage())
                    .duration(result.getDuration())
                    .timestamp(result.getCompletedAt())
                    .build();

            if (result.isSuccess()) {
                return ResponseEntity.ok(ApiResponse.success(response));
            } else {
                return ResponseEntity.ok(ApiResponse.error("脚本执行失败", response));
            }

        } catch (Exception e) {
            log.error("脚本执行异常: {} -> {}", requestDto.getNodeId(), requestDto.getCapabilityId(), e);
            return ResponseEntity.ok(ApiResponse.error("脚本执行异常: " + e.getMessage()));
        }
    }

    /**
     * 异步执行脚本
     */
    @PostMapping("/execute/async")
    public ResponseEntity<ApiResponse<String>> executeScriptAsync(
            @Valid @RequestBody ExecutionRequestDto requestDto) {

        log.info("异步执行脚本: {} -> {}", requestDto.getNodeId(), requestDto.getCapabilityId());

        try {
            ExecutionRequest request = ExecutionRequest.builder()
                    .nodeId(requestDto.getNodeId())
                    .capabilityId(requestDto.getCapabilityId())
                    .parameters(requestDto.getParameters())
                    .timeout(requestDto.getTimeout() != null ? requestDto.getTimeout() : 60)
                    .async(true)
                    .requestedAt(LocalDateTime.now())
                    .source("web")
                    .userId("system")
                    .build();

            if (!request.isValid()) {
                return ResponseEntity.badRequest()
                        .body(ApiResponse.error("无效的执行请求"));
            }

            String executionId = executionService.executeScriptAsync(request);
            return ResponseEntity.ok(ApiResponse.success(executionId, "脚本已开始异步执行"));

        } catch (Exception e) {
            log.error("异步脚本执行失败", e);
            return ResponseEntity.ok(ApiResponse.error("异步执行失败: " + e.getMessage()));
        }
    }

    /**
     * 获取执行结果
     */
    @GetMapping("/execution/{executionId}")
    public ResponseEntity<ApiResponse<ExecutionResponseDto>> getExecutionResult(
            @PathVariable String executionId) {

        log.debug("获取执行结果: {}", executionId);

        try {
            Optional<ExecutionResult> result = executionService.getExecutionResult(executionId);

            if (result.isEmpty()) {
                return ResponseEntity.ok(ApiResponse.error("未找到执行记录"));
            }

            ExecutionResult exec = result.get();
            ExecutionResponseDto response = ExecutionResponseDto.builder()
                    .executionId(exec.getExecutionId())
                    .nodeId(exec.getNodeId())
                    .capabilityId(exec.getCapabilityId())
                    .status(exec.getStatus().getCode())
                    .output(exec.getOutput())
                    .errorMessage(exec.getErrorMessage())
                    .duration(exec.getDuration())
                    .timestamp(exec.getCompletedAt())
                    .build();

            return ResponseEntity.ok(ApiResponse.success(response));

        } catch (Exception e) {
            log.error("获取执行结果失败: {}", executionId, e);
            return ResponseEntity.ok(ApiResponse.error("获取结果失败: " + e.getMessage()));
        }
    }

    /**
     * 取消执行
     */
    @PostMapping("/execution/{executionId}/cancel")
    public ResponseEntity<ApiResponse<String>> cancelExecution(
            @PathVariable String executionId) {

        log.info("取消执行: {}", executionId);

        try {
            boolean cancelled = executionService.cancelExecution(executionId);

            if (cancelled) {
                return ResponseEntity.ok(ApiResponse.success("执行已取消"));
            } else {
                return ResponseEntity.ok(ApiResponse.error("无法取消执行"));
            }

        } catch (Exception e) {
            log.error("取消执行失败: {}", executionId, e);
            return ResponseEntity.ok(ApiResponse.error("取消失败: " + e.getMessage()));
        }
    }

    /**
     * 获取执行历史
     */
    @GetMapping("/history/{nodeId}")
    public ResponseEntity<ApiResponse<List<ExecutionResponseDto>>> getExecutionHistory(
            @PathVariable String nodeId,
            @RequestParam(defaultValue = "10") int limit) {

        log.debug("获取执行历史: {} (limit: {})", nodeId, limit);

        try {
            List<ExecutionResult> history = executionService.getExecutionHistory(nodeId, limit);

            List<ExecutionResponseDto> response = history.stream()
                    .map(result -> ExecutionResponseDto.builder()
                            .executionId(result.getExecutionId())
                            .nodeId(result.getNodeId())
                            .capabilityId(result.getCapabilityId())
                            .status(result.getStatus().getCode())
                            .output(result.getOutput())
                            .errorMessage(result.getErrorMessage())
                            .duration(result.getDuration())
                            .timestamp(result.getCompletedAt())
                            .build())
                    .toList();

            return ResponseEntity.ok(ApiResponse.success(response));

        } catch (Exception e) {
            log.error("获取执行历史失败: {}", nodeId, e);
            return ResponseEntity.ok(ApiResponse.error("获取历史失败: " + e.getMessage()));
        }
    }

    /**
     * 获取执行统计
     */
    @GetMapping("/statistics")
    public ResponseEntity<ApiResponse<Object>> getExecutionStatistics() {
        log.debug("获取执行统计");

        try {
            ExecutionDomainService.ExecutionStatistics statistics = executionService.getExecutionStatistics();
            return ResponseEntity.ok(ApiResponse.success(statistics));

        } catch (Exception e) {
            log.error("获取执行统计失败", e);
            return ResponseEntity.ok(ApiResponse.error("获取统计失败: " + e.getMessage()));
        }
    }
}
